package com.studerb.view.tasks.failed;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import org.apache.log4j.Logger;
import org.bushe.swing.event.annotation.AnnotationProcessor;
import org.bushe.swing.event.annotation.EventSubscriber;

import com.studerb.events.TaskServiceEvent;
import com.studerb.events.TaskServiceEvent.EventType;
import com.studerb.tasks.interfaces.ITask;
import static com.studerb.util.Constants.EVENT_SERVICE_NAME;

public class FailedTasksTableModel extends AbstractTableModel {

    public enum Column {
        TITLE, MESSAGE
    }

    final private static String[] columnNames = new String[] {"Task Title", "Failed Message"};
    final private static boolean[] isEditable = new boolean[] {false, false};
    final private static Class[] columnClasses = new Class[] {String.class, String.class};

    //@Autowired private FailedTasksTable failedTasksTable;

    protected List<ITask> tasks = Collections.synchronizedList(new ArrayList<ITask>());
    Logger logger = Logger.getLogger(FailedTasksTableModel.class);

    public synchronized void addTask(ITask task) {
        if(tasks.contains(task)){
            throw new IllegalArgumentException("Task: " + task + " already added to model");
        }
        this.tasks.add(task);
        fireTableRowsInserted(tasks.size() - 1, tasks.size() - 1);
    }

    @Override public Class<?> getColumnClass(int columnIndex) {
        return columnClasses[columnIndex];
    }

    @Override public int getColumnCount() {
        return columnNames.length;
    }

    @Override public String getColumnName(int columnIndex) {
        return columnNames[columnIndex];
    }

    @Override public int getRowCount() {
        return tasks.size();
    }

    @Override public Object getValueAt(int rowIndex, int columnIndex) {
        ITask task = tasks.get(rowIndex);
        Column column = Column.values()[columnIndex];
        switch(column){
            case TITLE:
                return task.getTitle();
            case MESSAGE:
                return task.getMessage();
            default:
                throw new IllegalArgumentException("Column[TITLE, PROGRESS]: " + columnIndex + " not supported");
        }
    }

    public void init() {
        AnnotationProcessor.process(this);
    }

    @Override public boolean isCellEditable(int rowIndex, int columnIndex) {
        return isEditable[columnIndex];
    }

    public synchronized void removeTask(ITask t) {
        int taskIndex = tasks.indexOf(t);
        if(taskIndex == -1){
            logger.warn("Tasks does not contain task: " + t.toString() + "\tIgnoring Task");
            return;
        }
        this.tasks.remove(t);
        fireTableRowsDeleted(taskIndex, taskIndex);
    }

    @Override public void setValueAt(Object value, int rowIndex, int columnIndex) {
        throw new UnsupportedOperationException("Task Table does not have editable table cells");
    }

    @EventSubscriber(eventServiceName = EVENT_SERVICE_NAME) public void onEvent(TaskServiceEvent evt) {
        ITask task = evt.getTask();
        EventType type = evt.getType();
        TaskServiceEvent.Queue queue = evt.getQueue();
        if(queue == TaskServiceEvent.Queue.FAILED){
            switch(type){
                case ADDED:
                    logger.debug("Task: " + task + " added to Failed queue");
                    this.addTask(task);
                    break;
                case REMOVED:
                    logger.debug("Task: " + task + " removed from Failed queue");
                    this.removeTask(task);
                    break;
                default: break;
            }
        }
    }
}
